package utils

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"log/slog"
	"os"
	"strconv"
	"strings"

	"github.com/avast/apkparser"
	"github.com/beevik/etree"
)

type ApkInfo struct {
	PackageName       string `json:"packageName"`
	VersionCode       int64  `json:"versionCode"`
	VersionName       string `json:"versionName"`
	CompileSdkVersion int64  `json:"compileSdkVersion"`
	MinSdkVersion     int64  `json:"minSdkVersion"`
	TargetSdkVersion  int64  `json:"targetSdkVersion"`
	LaunchActivity    string `json:"launchActivity"`
	FileName          string `json:"fileName"`
	FilePath          string `json:"filePath"`
	FileSize          int64  `json:"fileSize"`
	FileMD5           string `json:"fileMd5"`
	Label             string `json:"label"`
	Icon              string `json:"icon"`
	IconPath          string `json:"iconPath"`
}

func ParseApk(apkFilePath string) (ApkInfo, error) {
	var apkInfo ApkInfo

	// 文件信息
	if fileInfo, err := os.Stat(apkFilePath); err != nil {
		slog.Error("Failed to open the apk file", "apkFilePath", apkFilePath, "err", err.Error())
		return ApkInfo{}, err
	} else {
		apkInfo.FilePath = apkFilePath
		apkInfo.FileName = fileInfo.Name()
		apkInfo.FileSize = fileInfo.Size()
		apkInfo.FileMD5, _ = MD5File(apkFilePath)
	}

	// 解析apk文件信息
	buffer := new(bytes.Buffer)
	enc := xml.NewEncoder(buffer)
	enc.Indent("", "\t")
	zipErr, resErr, manErr := apkparser.ParseApk(apkFilePath, enc)
	if zipErr != nil {
		slog.Error("Failed to parse the apk file", "apkFilePath", apkFilePath, "err", zipErr.Error())
		return ApkInfo{}, zipErr
	}

	if resErr != nil {
		slog.Error("Failed to parse resources", "err", resErr.Error())
		return ApkInfo{}, resErr
	}
	if manErr != nil {
		slog.Error("Failed to parse AndroidManifest.xml", "err", manErr.Error())
		return ApkInfo{}, manErr
	}

	var doc = etree.NewDocument()
	if err := doc.ReadFromBytes(buffer.Bytes()); err != nil {
		slog.Error("Failed to parse xml", "err", err.Error())
		return ApkInfo{}, err
	}

	var root = doc.Root()

	var compileSdkVersionAttr = root.SelectAttr("android:compileSdkVersion")
	if compileSdkVersionAttr != nil {
		apkInfo.CompileSdkVersion, _ = strconv.ParseInt(compileSdkVersionAttr.Value, 10, 64)
	}
	var minSdkVersionAttr = root.SelectAttr("android:minSdkVersion")
	if minSdkVersionAttr != nil {
		apkInfo.MinSdkVersion, _ = strconv.ParseInt(minSdkVersionAttr.Value, 10, 64)
	}
	var targetSdkVersionAttr = root.SelectAttr("android:targetSdkVersion")
	if targetSdkVersionAttr != nil {
		apkInfo.TargetSdkVersion, _ = strconv.ParseInt(targetSdkVersionAttr.Value, 10, 64)
	}

	var usesSdk = root.SelectElement("uses-sdk")
	if usesSdk != nil {
		compileSdkVersionAttr = usesSdk.SelectAttr("android:compileSdkVersion")
		if compileSdkVersionAttr != nil {
			apkInfo.CompileSdkVersion, _ = strconv.ParseInt(compileSdkVersionAttr.Value, 10, 64)
		}
		minSdkVersionAttr = usesSdk.SelectAttr("android:minSdkVersion")
		if minSdkVersionAttr != nil {
			apkInfo.MinSdkVersion, _ = strconv.ParseInt(minSdkVersionAttr.Value, 10, 64)
		}
		targetSdkVersionAttr = usesSdk.SelectAttr("android:targetSdkVersion")
		if targetSdkVersionAttr != nil {
			apkInfo.TargetSdkVersion, _ = strconv.ParseInt(targetSdkVersionAttr.Value, 10, 64)
		}
	}

	apkInfo.VersionCode, _ = strconv.ParseInt(root.SelectAttr("android:versionCode").Value, 10, 64)
	apkInfo.VersionName = root.SelectAttr("android:versionName").Value
	apkInfo.PackageName = root.SelectAttr("package").Value

	var applicationEle = root.SelectElement("application")
	apkInfo.Label = applicationEle.SelectAttr("android:label").Value
	apkInfo.Icon = applicationEle.SelectAttr("android:icon").Value

	// 查找启动activity
	var activities = applicationEle.SelectElements("activity")
	for _, activity := range activities {
		var categories = activity.FindElements("./intent-filter/category")
		if len(categories) > 0 {
			for _, category := range categories {
				if category.SelectAttr("android:name").Value == "android.intent.category.LAUNCHER" {
					apkInfo.LaunchActivity = activity.SelectAttr("android:name").Value
					break
				}
			}
		}
		if len(apkInfo.LaunchActivity) > 0 {
			break
		}
	}

	// 解压文件，获取图标
	var unzipDirPath = apkFilePath[:strings.LastIndex(apkFilePath, ".")]
	if err := Unzip(apkFilePath, unzipDirPath); err != nil {
		slog.Error("Failed to unzip the apk file", "apkFilePath", apkFilePath, "err", err.Error())
		return ApkInfo{}, err
	}

	var destIconPath = apkFilePath[:strings.LastIndex(apkFilePath, "/")] +
		"/" + apkInfo.FileName[:strings.LastIndex(apkInfo.FileName, ".")] +
		"_" + apkInfo.Icon[strings.LastIndex(apkInfo.Icon, "/")+1:]

	if err := os.Rename(unzipDirPath+"/"+apkInfo.Icon, destIconPath); err != nil {
		slog.Error("Failed to rename the icon file", "iconFilePath", unzipDirPath+"/"+apkInfo.Icon, "err", err.Error())
		return ApkInfo{}, err
	}
	apkInfo.IconPath = destIconPath

	// 删除解压后的文件目录
	err := os.RemoveAll(unzipDirPath)
	if err != nil {
		slog.Error(err.Error())
	}

	apkInfoData, _ := json.Marshal(apkInfo)
	fmt.Println(string(apkInfoData))
	return apkInfo, nil
}
